<?php
/**
 * Created by PhpStorm.
 * User: UsWork-02
 * Date: 2021/7/13
 * Time: 15:22
 */

namespace app\api\controller;
use app\common\controller\Mqtt;
use think\Config;
use think\Controller;
use think\Db;
use think\Exception;

class Charging extends Controller
{
    //test
    public function test(){

        $content = "2a0c1b0002000000003f0523";

        $division = $this->division($content);
        $division = explode(" ",$division);

        echo $division['4'];  //端口号
        echo $division['5'];  //端口号
        echo $division['6'];  //端口号
        dump($division);die;

        $data['contetn'] = $content;

        echo "1111";die;
    }


    //组装回复内容
    public function assemble($contetnt){
        $checkContetn = pack('H*',$contetnt);
        $res = $this->crc16($checkContetn);
        $low = dechex($res %256);// 低八位
        $high =  dechex(floor($res /256));// 高8位
        if(strlen($low)==1){
            $low = "0".$low;
        }
        if(strlen($high)==1){
            $high = "0".$high;
        }
        $contetnt = strtoupper($contetnt.$low.$high.'23');
//        $contetnt = strtoupper($contetnt.$high.$low.'23');
        return $contetnt;
    }


    //发送主题
    public function sendout($username="test",$contetnt=0,$instructions=0){
            try{

                $data['contetn'] = $contetnt;
                $data['instructions'] = $instructions;
                $data['username'] = $username;
                $data['addtime'] = date("Y-m-d H:i:s");
                $data['type'] = 2;
                $Stakeoperation = new Stakeoperation();
                $Stakeoperation->handle("test",$data);

                //        $this->newtext1($contetnt,"sendout.txt");
//        $contetn = $this->str2hex($contetn);
                $contetnt = hex2bin($contetnt);
                $server = "127.0.0.1";     // 服务代理地址(mqtt服务端地址)
//        $server = "123.207.201.105";     // 服务代理地址(mqtt服务端地址)
                $port = 1883;                     // 通信端口
                $username = $username;                   // 用户名(如果需要)
                $password = "";                   // 密码(如果需要
                $client_id = "server"; // 设置你的连接客户端id
                $mqtt = new Mqtt($server, $port, $client_id); //实例化MQTT类
                if ($mqtt->connect(true, NULL, $username, $password)) {
                    //如果创建链接成功
                    $mqtt->publish("/Issue/", $contetnt, 0);
                    // 发送到 xxx3809293670ctr 的主题 一个信息 内容为 setr=3xxxxxxxxx Qos 为 0
                    $mqtt->close();    //发送后关闭链接
                    return true;
                } else {
                    return false;
                }
            }catch (Exception $e){
                return false;
            }
    }

    //接收设备信息
    public function receive(){
        try{
            $instructions = Config::get("Charging_device");
            $body = file_get_contents('php://input');

            $this->newtext1($body,"test111.txt");

//            $body = "* pX\v�x� 
// A,#,1CDZ022106070001,/up/1CDZ022106070001, 1626421070429, emqx@127.0.0.1,1CDZ022106070001";
//            dump($body);die;
            $body = explode(";",$body);

//           $content =  $body[0];
            $content = bin2hex($body[0]);
            //解析操作指令
            $division = $this->division($content);
            $division = explode(" ",$division);
            $data['contetn'] = $content;
            $data['username'] = empty($body[1])?'username':$body[1];
            $data['topic'] = empty($body[2])?'topic':$body[2];
            $data['timestamp'] = empty($body[3])?'timestamp':$body[3];
            $data['node'] = empty($body[4])?'node':$body[4];
            $data['clientid'] = empty($body[5])?'clientid':$body[5];
            $data['addtime'] = date("Y-m-d H:i:s");
            if(!empty($division[2])){
                $data['instructions'] = empty($instructions[$division[2]])?"其他指令":$instructions[$division[2]];
            }
            $instructions = '';
            $username = $data['username'];
            $Stakeoperation = new Stakeoperation();
            $Stakeoperation->handle("test",$data);  //记录操作命令行

            if(!empty($division[2])){
                switch ($division[2]){
                    case '11':  //设备心跳
                        $returnContetnt = "2A07A101";
                        $instructions = "应答设备心跳";
                        $Stakeoperation->heartbeat($username);  //记录数据库操作
                        break;
                    case 'b0':  //刷卡操作
                        $returnContetnt = "2A0CB0010101010800";
                        $instructions = "应答刷卡操作";
                        $Stakeoperation->updateConfig($username,$division);  //记录数据库操作
                        break;
                    case '26':  //设备GPRS 模块IMEI
                        $IMEI = "";
                        for ($i=3;$i<=17;$i++){
                            $IMEI .= $division[$i];
                        }
                        $Stakeoperation->updateImei($username,$IMEI,"IMEI");  //记录数据库操作
                        break;
                    case '12':  //设备GPRS 信号强度
                        $data = $division[3];
                        $Stakeoperation->updateImei($username,$data,"signal");  //记录数据库操作
                        break;
                    case '15': //设置设备参数回调
                        $data = $division[3];
                        $Stakeoperation->updateConfig($username,$data);  //记录数据库操作
                        break;
                    case '16': //获取设备配置回调
                        $Stakeoperation->synchroConfig($username,$division);  //记录数据库操作
                        break;
                    case '1b': //查询单端口剩余时间
                        $Stakeoperation->updatePort($username,$division);  //记录数据库操作
                        break;
                    case '1e': //服务器启动单端口回调
                        $Stakeoperation->updatePort($username,$division);  //记录数据库操作
                        break;
                    case '1c': //电量更新主动上报
                        $Stakeoperation->cumulativeAd($username,$division);  //记录数据库操作
                        break;
                    case '1f': //服务器停止单端口回调
                        $status = hexdec($division[4]);  //状态
                        if(!empty($status)){
                            $Stakeoperation->stopPort($username,$division,1);  //记录数据库操作
                        }
                        break;
                    case '21': //设备端口主动停机上报服务器指令
                        $Stakeoperation->stopPort($username,$division,1);  //记录数据库操作
                        $returnContetnt = "2A07B1".$division[3];
                        $instructions = "服务器接收设备主动停机状态返回指令";
                        break;
                    case '22': //设备总功率异常主动上报服务器指令
                        $data = hexdec($division[3].$division[4]);  //类型  剩余时间or剩余电量
                        $Stakeoperation->updateImei($username,$data,"power");  //记录设备异常状态
                        $returnContetnt = "2A06B2";
                        $instructions = "服务器接收设备总功率异常状态返回指令";
                        break;
                    case '23': //设备机箱温度异常主动上报服务器指令
                        $Stakeoperation->updateStake($username,$division,"temperature");  //记录数据库操作
                        $returnContetnt = "2A06B3";
                        $instructions = "服务器接收设备温度异常状态返回指令";
                        break;
                    case '19': //设备历史总电量
                        $Stakeoperation->updateStake($username,$division,"totalElectric");  //记录数据库操作
                        break;
                    case '17': //设备机箱实时温度值返回
                        $Stakeoperation->updateStake($username,$division,"temperatureValue");  //记录数据库操作
                        break;
                    case '1a': //设备机箱实时温度值返回
                        $Stakeoperation->updateStake($username,$division,"power");  //记录数据库操作
                        break;
                    default:
                        break;
                }
            }else{
                $returnContetnt = "2A07A103";
            }
            //指令操作不为空时回复
            if(!empty($returnContetnt)){
                $returnContetnt = $this->assemble($returnContetnt);
                $this->sendout($username,$returnContetnt,$instructions);
            }
            echo "操作成功";
        }catch (Exception $e){
            echo $e->getMessage();
        }
    }

    //查询设备GPRS 信号强度指令
    public function selGprs(){
        $username = empty($_GET['username'])?"1CDZ022106070001":$_GET['username'];
        $content = empty($_GET['content'])?"2A06A2":$_GET['content'];
        $instructions = empty($_GET['instructions'])?"":$_GET['instructions'];
        $content = $this->assemble($content);
        $black = $this->sendout($username,$content,$instructions);
        if($black){
            echo "发送成功";
        }else{
            echo "发送失败";
        }
    }


    //调试方法
    public function message(){
        switch(!empty($_SERVER['CONTENT_TYPE'])){
            case 'application/json':
                // 这里通过输入端来获取数据
                $body = file_get_contents('php://input');
                $this->newtext1($body,"message.txt");
                break;
        }
    }

    //调试方法
    public function testApi(){
        $username = "1CDZ022106070001";
        $content = "2a061193a423";  //查询设备心跳
        $contetnt = "2A07A101";
        $this->sendout($username,$contetnt);
    }


    /**
     **16进制转字符串
     **/
    public function Hex2String($hex)
    {
        $string = '';
        for ($i = 0; $i < strlen($hex) - 1; $i += 2) {
            $string .= chr(hexdec($hex[$i] . $hex[$i + 1]));
        }
        return $string;
    }

    /**
     * 字符串转16进制字符串
     * 传入字符串格式：001624180101
     */
    function str2hex($string)
    {
        $str = '';
        for ($i = 0; $i < strlen($string); $i += 2) {
            $str .= chr(hexdec(substr($string, $i, 2)));
        }
        return $str;
    }

    //16进制分割
    public function division($assembly){
        $hex_data = str_split(str_replace(' ', '', $assembly), 2);
        $new_data = "";
        foreach ($hex_data as $item){
            $new_data .= $item." ";
        }
        $new_data = trim($new_data," ");
        return $new_data;
    }

    //php crc16校验计算
    function crc16($string) {
        $crc = 0xFFFF;
        for ($x = 0; $x < strlen ($string); $x++) {
            $crc = $crc ^ ord($string[$x]);
            for ($y = 0; $y < 8; $y++) {
                if (($crc & 0x0001) == 0x0001) {
                    $crc = (($crc >> 1) ^ 0xA001);
                } else { $crc = $crc >> 1; }
            }
        }
        return $crc;
    }


    function newtext($params){
        $myfile = fopen(__DIR__."/newfile.txt", "a") or die("Unable to open file!");//这个是在c盘根目录生成文件
        $txt = $params;//获取参数
        $b="";
        foreach($txt as $k=>$v){
            $b = $b ."[".$k."]=>".$v."\n";
        }
        fwrite($myfile, $b);//写入内容,可以写多次哦,不过没啥意义,因为你拼接好字符串,一次写入就行了
        fclose($myfile);//关闭该操作
    }


    function newtext1($params,$faleName="newfile1.txt"){
        $myfile = fopen(__DIR__."/".$faleName, "a") or die("Unable to open file!");//这个是在c盘根目录生成文件
        $txt = $params;//获取参数

        fwrite($myfile, $txt);//写入内容,可以写多次哦,不过没啥意义,因为你拼接好字符串,一次写入就行了
        fclose($myfile);//关闭该操作
    }


}